#include <drv/serial.h>

#include <arch/io.h>

#include <utils/lock.h>

#include <third-party/nanoprintf.h>

static uint16_t serial_port = 0;
static uint32_t serial_baudrate = 0;

void serial_init(uint16_t port, uint32_t baudrate) {
	if(115200 % baudrate) {
		return;
	}

	uint32_t divisor = 115200 / baudrate;

	//  关中断
	io_write8(port + 1, 0x00);

	//  设置波特率除数
	io_write8(port + 3, 0x80);
	io_write8(port + 0, divisor & 0xff);
	io_write8(port + 1, (divisor >> 8) & 0xff);

	io_write8(port + 3, 0x03);	//  设置连接参数(8N1)
	io_write8(port + 2, 0xc7);	//  启用带14字节缓冲的FIFO

	//  测试端口能否收发数据
	io_write8(port + 4, 0x1b);

	io_write8(port, 0x12);
	if(io_read8(port) != 0x12) {
		return;
	}

	io_write8(port + 4, 0x0b);

	serial_port = port;
	serial_baudrate = baudrate;
}

void serial_write_byte(uint8_t byte) {
	if(serial_port == 0) {
		return;
	}

	while((io_read8(serial_port + 5) & 0x20) == 0);
	io_write8(serial_port, byte);
}

void serial_write(void *data, uint32_t len) {
	for(uint32_t i = 0; i < len; i++) {
		serial_write_byte(((uint8_t *)data)[i]);
	}
}

static void serial_putc(int c, void *unused __attribute__((unused))) {
	if(c == '\n') {
		serial_write_byte('\r');
	}

	serial_write_byte((uint8_t)c);
}

static lock_t serial_print_lock;

int serial_printf(const char *fmt, ...) {
	lock_acquire(&serial_print_lock);

	va_list args;
	va_start(args, fmt);
	int result = npf_vpprintf(serial_putc, NULL, fmt, args);
	va_end(args);

	lock_release(&serial_print_lock);

	return result;
}

uint16_t serial_get_port() {
	return serial_port;
}

uint32_t serial_get_baudrate() {
	return serial_baudrate;
}